#include "dexiosfmtab.h"

#include <QComboBox>
#include <QDebug>
#include <QDesktopServices>
#include <QFileSystemModel>
#include <QMenu>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QToolBar>
#include <QTreeView>
#include <QVBoxLayout>

#include "dexiosfmdirview.h"

DexiosFMTab::DexiosFMTab(QAbstractItemModel * model, QWidget * parent, Qt::WindowFlags f)
	: QWidget(parent, f),
	  back_history(new QMenu(this)),
	  dir_view(new DexiosFMDirView(this)),
	  file_system((QFileSystemModel *)model),
	  forward_history(new QMenu(this)),
	  layout(new QVBoxLayout(this)),
	  location_box(new QComboBox(this)),
	  main_toolbar(new QToolBar(this)),
	  proxy_file_system(new QSortFilterProxyModel(this)),
	  trash_bin(QDesktopServices::storageLocation(QDesktopServices::HomeLocation) + "/.local/share/Trash/files")
	{
		dir_view->setModel(proxy_file_system);
		dir_view->sortByColumn(2, Qt::AscendingOrder);

		connect(dir_view, SIGNAL(openPath()),
				this, SLOT(openPath()));
		connect(dir_view, SIGNAL(previewImage()),
				this, SIGNAL(previewImage()));

		layout->addWidget(main_toolbar);
		layout->addWidget(location_box);
		layout->addWidget(dir_view);
		layout->setContentsMargins(0, 0, 0, 0);
		layout->setSpacing(0);

		location_box->setEditable(true);
		location_box->setInsertPolicy(QComboBox::InsertAtTop);

		connect(location_box, SIGNAL(activated(QString)),
				this, SLOT(openPath(QString)));

		QPushButton * back_button = new QPushButton(main_toolbar);
		back_button->setEnabled(false);
		back_button->setFlat(true);
		back_button->setIcon(QIcon::fromTheme("go-previous", QIcon(":/icons/go-previous.png")));
		back_button->setMenu(back_history);
		back_button->setText(tr("Go Back"));

		connect(this, SIGNAL(enableGoBackAction(bool)),
				back_button, SLOT(setEnabled(bool)));

		QPushButton * up_button = new QPushButton(main_toolbar);
		up_button->setEnabled(false);
		up_button->setFlat(true);
		up_button->setIcon(QIcon::fromTheme("go-up", QIcon(":/icons/go-up.png")));
		up_button->setText(tr("Go Up"));

		connect(up_button, SIGNAL(clicked()),
				this, SLOT(goUp()));

		connect(this, SIGNAL(enableGoUpAction(bool)),
				up_button, SLOT(setEnabled(bool)));

		QPushButton * fwd_button = new QPushButton(main_toolbar);
		fwd_button->setEnabled(false);
		fwd_button->setFlat(true);
		fwd_button->setIcon(QIcon::fromTheme("go-next", QIcon(":/icons/go-next.png")));
		fwd_button->setMenu(forward_history);
		fwd_button->setText(tr("Go Forward"));

		main_toolbar->addWidget(back_button);
		main_toolbar->addWidget(up_button);
		main_toolbar->addWidget(fwd_button);

		proxy_file_system->setSourceModel(model);
		proxy_file_system->setDynamicSortFilter(true);

//		connect(proxy_file_system, SIGNAL(layoutChanged()),
//				this, SLOT(updateImageListing()));

		connect(dir_view, SIGNAL(activated(QModelIndex)),
				this, SLOT(openPath(QModelIndex)));
		connect(dir_view, SIGNAL(clicked(QModelIndex)),
				this, SLOT(emitActionSignalsItemClicked(QModelIndex)));
	}

QModelIndex DexiosFMTab::currentIndex() const
	{
		return proxy_file_system->mapToSource(dir_view->selectionModel()->currentIndex());
	}

void DexiosFMTab::emitActionSignalsItemClicked(const QModelIndex & index)
	{
		emit enableDeleteAction(true);
		emit enableRenameAction(true);

		if (file_system->isDir(proxy_file_system->mapToSource(index)))
			emit enableAddToFavorites(true);
		else
			emit enableAddToFavorites(false);
	}

QModelIndex DexiosFMTab::firstImage()
	{
		QRegExp regex("\\.(?:jpe?g|gif|png|bmp|xbm|xpm|pbm|pgm|ppm|tiff)$",
					  Qt::CaseInsensitive);

		QModelIndex index = proxy_file_system->index(0, 0, dir_view->rootIndex());
		QModelIndex index_mapped = proxy_file_system->mapToSource(index);

		QString file_name = file_system->fileName(index_mapped);

		dir_view->selectionModel()->setCurrentIndex(index,
													QItemSelectionModel::SelectCurrent);

		if (!file_name.contains(regex))
			return nextImage();

		return index_mapped;
	}

void DexiosFMTab::goUp()
	{
		QModelIndex index = dir_view->rootIndex();
		if (index.parent().isValid())
			openPath(index.parent());
	}

bool DexiosFMTab::isItemSelected()
	{
		return dir_view->selectionModel()->isSelected(dir_view->currentIndex());
	}

QModelIndex DexiosFMTab::lastImage()
	{
		QRegExp regex("\\.(?:jpe?g|gif|png|bmp|xbm|xpm|pbm|pgm|ppm|tiff)$",
					  Qt::CaseInsensitive);

		QModelIndex index = proxy_file_system->index(proxy_file_system->rowCount(dir_view->rootIndex()) - 1,
													 0, dir_view->rootIndex());
		QModelIndex index_mapped = proxy_file_system->mapToSource(index);

		QString file_name = file_system->fileName(index_mapped);

		dir_view->selectionModel()->setCurrentIndex(index,
													QItemSelectionModel::SelectCurrent);

		if (!file_name.contains(regex))
			return previousImage();

		return index_mapped;
	}

QModelIndex DexiosFMTab::nextImage()
	{
		QModelIndexList list = dir_view->selectionModel()->selectedIndexes();
		QModelIndex index = list.at(0);
		QModelIndex index_mapped = proxy_file_system->mapToSource(list.at(0));

		QRegExp regex("\\.(?:jpe?g|gif|png|bmp|xbm|xpm|pbm|pgm|ppm|tiff)$", Qt::CaseInsensitive);

		if (file_system->fileInfo(index_mapped).exists())
		{
			QString file_name = file_system->fileName(index_mapped);

			do
			{
				index = dir_view->indexBelow(index);
				index_mapped = proxy_file_system->mapToSource(index);
				file_name = file_system->filePath(index_mapped);
			}

			while (!file_name.contains(regex) && index.isValid());

			dir_view->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
			return index_mapped;
		}

		else
		{
			index = firstImage();
			index_mapped = proxy_file_system->mapToSource(index);
			return index_mapped;
		}
	}

void DexiosFMTab::openPath()
	{
		QModelIndexList list = dir_view->selectionModel()->selectedIndexes();
		if (list.at(0).isValid())
			openPath(list.at(0));
	}

void DexiosFMTab::openPath(const QString & path)
	{
		openPath(file_system->index(path), true);
	}

void DexiosFMTab::openPath(const QModelIndex & i, bool b)
	{
		QModelIndex index(i);

		if (index.model() == proxy_file_system)
			index = proxy_file_system->mapToSource(index);

		if (file_system->isDir(index))
		{
			if (index.parent().isValid())
				enableGoUpAction(true);
			else
				enableGoUpAction(false);

			if (b)
			{
				QString path = file_system->filePath(proxy_file_system->mapToSource(dir_view->rootIndex()));
				QAction * act = new QAction(path, back_history);
				back_history->insertAction(0, act);
			}

			if (back_history->actions().count())
				emit enableGoBackAction(true);
			else
				emit enableGoBackAction(false);

			dir_view->sortByColumn(0, Qt::AscendingOrder);
			dir_view->sortByColumn(2, Qt::AscendingOrder);
			dir_view->setRootIndex(proxy_file_system->mapFromSource(index));

			location_box->setEditText(file_system->filePath(index));

			emit enableAddToFavorites(false);
			emit enableDeleteAction(false);
			emit enableRenameAction(false);

			// Unix(-like) systems require extra steps to get the desired effect.
			// Until then, only Windows will have support for creating directories.
#ifdef Q_WS_WIN
			int perm = file_system->permissions(index);
			if (perm | QFile::WriteUser)
				emit enableNewDirAction(true);
			else
				emit enableNewDirAction(false);
#endif

			currentPathChanged(this, index.data().toString());
		}

		else if (file_system->fileInfo(index).exists())
		{
#ifdef Q_WS_WIN
			QDesktopServices::openUrl(QUrl("file:///" + file_system->filePath(proxy_file_system->mapToSource(index)),
										   QUrl::TolerantMode));
#endif
		}
	}

QModelIndex DexiosFMTab::previousImage()
	{
		QModelIndexList list = dir_view->selectionModel()->selectedIndexes();
		QModelIndex index = list.at(0);
		QModelIndex index_mapped = proxy_file_system->mapToSource(list.at(0));

		QRegExp regex("\\.(?:jpe?g|gif|png|bmp|xbm|xpm|pbm|pgm|ppm|tiff)$",
					  Qt::CaseInsensitive);

		if (file_system->fileInfo(index_mapped).exists())
		{
			QString file_name = file_system->fileName(index_mapped);

			do
			{
				index = dir_view->indexAbove(index);
				index_mapped = proxy_file_system->mapToSource(index);
				file_name = file_system->filePath(index_mapped);
			}

			while (!file_name.contains(regex) && index.isValid());

			dir_view->selectionModel()->setCurrentIndex(index,
														QItemSelectionModel::SelectCurrent);
			return index_mapped;
		}

		else
		{
			index = lastImage();
			index_mapped = proxy_file_system->mapToSource(index);
			return index_mapped;
		}
	}

QModelIndex DexiosFMTab::rootIndex() const
	{
		return proxy_file_system->mapToSource(dir_view->rootIndex());
	}
